package com.app;

import java.awt.BorderLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseListener;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.table.DefaultTableModel;

import com.db.DBCreator;
import com.trade.TradeBean;

public class TradeSelector extends JFrame implements ActionListener {

	private static final long serialVersionUID = 1L;
	private JPanel jContentPane = null;
	private JScrollPane buyTradesSelector = null;
	private JScrollPane sellTradesSelector = null;
	private JTable buyTradesTable = null;
	private JTable sellTradesTable = null;
	private JButton reconcile = null;
	private final JTable baseTable;

	/**
	 * This is the default constructor
	 */
	public TradeSelector() {
		super();
		this.baseTable = null;
		initialize();
	}

	public TradeSelector(TradeBean tb) {
		super();
		this.baseTable = null;
		initialize(tb);
	}

	public TradeSelector(TradeBean tb, JTable tradeTable) {
		super();
		this.baseTable = tradeTable;
		initialize(tb);
	}

	/**
	 * This method initializes this
	 * 
	 * @return void
	 */
	private void initialize() {
		this.setSize(300, 200);
		this.setAlwaysOnTop(true);
		this.setContentPane(getJContentPane());
		this.setTitle("Trade Selector");

	}

	private void initialize(TradeBean tb) {
		this.setSize(300, 200);
		this.setContentPane(getJContentPane(tb));
		this.setTitle("Trade Selector");

	}

	/**
	 * This method initializes jContentPane
	 * 
	 * @return javax.swing.JPanel
	 */
	private JPanel getJContentPane() {
		if (jContentPane == null) {
			jContentPane = new JPanel();
			jContentPane.setLayout(new BorderLayout());
			jContentPane.add(getBuyTradesSelector(), BorderLayout.NORTH);
			jContentPane.add(new JSeparator(SwingConstants.HORIZONTAL));
			jContentPane.add(getReconcile(), BorderLayout.SOUTH);
		}
		return jContentPane;
	}

	private JPanel getJContentPane(TradeBean tb) {
		if (jContentPane == null) {
			jContentPane = new JPanel();
			jContentPane.setLayout(new BorderLayout());
			jContentPane.add(getSellTradesSelector(tb), BorderLayout.NORTH);
			jContentPane.add(getBuyTradesSelector(tb), BorderLayout.CENTER);

			buyTradesTable.removeColumn(buyTradesTable.getColumn("OrderRef"));
			buyTradesTable.removeColumn(buyTradesTable.getColumn("Settlement"));
			buyTradesTable.removeColumn(buyTradesTable.getColumn("Segment"));
			buyTradesTable.removeColumn(buyTradesTable.getColumn("Exchange"));
			buyTradesTable.removeColumn(buyTradesTable
					.getColumn("DPIdClientDPId"));
			sellTradesTable.removeColumn(sellTradesTable.getColumn("OrderRef"));
			sellTradesTable.removeColumn(sellTradesTable
					.getColumn("Settlement"));
			sellTradesTable.removeColumn(sellTradesTable.getColumn("Segment"));
			sellTradesTable.removeColumn(sellTradesTable.getColumn("Exchange"));
			sellTradesTable.removeColumn(sellTradesTable
					.getColumn("DPIdClientDPId"));
			jContentPane.add(getReconcile(), BorderLayout.SOUTH);
			MouseListener popupListener = new PopupListener(buyTradesTable);
			buyTradesTable.addMouseListener(popupListener);
		}
		return jContentPane;
	}

	/**
	 * This method initializes buyTradesSelector
	 * 
	 * @return javax.swing.JScrollPane
	 */
	private JScrollPane getBuyTradesSelector() {
		if (buyTradesSelector == null) {
			buyTradesSelector = new JScrollPane();
			buyTradesSelector
					.setViewportView(getBuyTradesTable(new TradeBean()));
		}
		return buyTradesSelector;
	}

	private JScrollPane getBuyTradesSelector(TradeBean tb) {
		if (buyTradesSelector == null) {
			buyTradesSelector = new JScrollPane();
			buyTradesSelector.setViewportView(getBuyTradesTable(tb));
		}
		return buyTradesSelector;
	}

	private JScrollPane getSellTradesSelector(TradeBean tb) {
		if (sellTradesSelector == null) {
			sellTradesSelector = new JScrollPane();
			sellTradesSelector.setViewportView(getSellTradesTable(tb));
		}
		return sellTradesSelector;
	}

	/**
	 * This method initializes buyTradesTable
	 * 
	 * @return javax.swing.JTable
	 */
	private JTable getBuyTradesTable(TradeBean tb) {
		Field[] f = TradeBean.class.getDeclaredFields();
		if (buyTradesTable == null) {
			String[] columnNames = new String[f.length + 1];
			for (int i = 0; i < f.length; i++) {
				columnNames[i] = f[i].getName();
			}

			columnNames[f.length] = "Select";
			Connection con = DBCreator.getConnection();
			String sql = "select * from trades t where stock=? and action!='Sell' and date<=? and not exists(select 1 from reconciledtrades where t.tradeid=buyTradeId group by buyTradeId having sum(buyQty)>=t.\"Qty.\")";
			ResultSet rs = null;
			int count = 0;
			try {
				PreparedStatement pstmt = con.prepareStatement(sql,
						ResultSet.TYPE_SCROLL_INSENSITIVE,
						ResultSet.CONCUR_READ_ONLY);
				pstmt.setString(1, tb.getStock());
				// Date d = Date.parse(tb.getDate());
				pstmt.setDate(2, tb.getDate());
				rs = pstmt.executeQuery();
				rs.last();
				count = rs.getRow();
				rs.beforeFirst();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println("no of rows = " + count);

			Object[][] data = new Object[count][f.length + 1];
			try {
				int row = 0;
				while (rs.next()) {
					for (int i = 0; i < rs.getMetaData().getColumnCount(); i++) {
						data[row][i] = rs.getObject(i + 1);
					}
					data[row][f.length] = Boolean.FALSE;
					row++;
				}
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			DefaultTableModel dtm = new DefaultTableModel(data, columnNames);
			JTable table = new JTable(dtm) {
				// Returning the Class of each column will allow different
				// renderers to be used based on Class

				public Class getColumnClass(int column) {
					return getValueAt(0, column).getClass();
				}
			};
			table.setPreferredScrollableViewportSize(table.getPreferredSize());
			buyTradesTable = table;
		}
		return buyTradesTable;
	}

	private JTable getSellTradesTable(TradeBean tb) {
		Field[] f = TradeBean.class.getDeclaredFields();
		if (sellTradesTable == null) {
			String[] columnNames = new String[f.length];
			for (int i = 0; i < f.length; i++) {
				columnNames[i] = f[i].getName();
			}

			Object[][] data = new Object[1][f.length];
			data[0][0] = tb.getTradeID();
			data[0][1] = tb.getDate();
			data[0][2] = tb.getStock();
			data[0][4] = tb.getQty();
			DefaultTableModel dtm = new DefaultTableModel(data, columnNames);
			JTable table = new JTable(dtm) {
				// Returning the Class of each column will allow different
				// renderers to be used based on Class

				public Class getColumnClass(int column) {
					if (getValueAt(0, column) == null) {
						return String.class;
					}
					return getValueAt(0, column).getClass();
				}
			};
			table.setPreferredScrollableViewportSize(table.getPreferredSize());
			sellTradesTable = table;
		}
		return sellTradesTable;
	}

	/**
	 * This method initializes reconcile
	 * 
	 * @return javax.swing.JButton
	 */
	private JButton getReconcile() {

		if (reconcile == null) {
			reconcile = new JButton("Reconcile Selected Trades");
		}
		reconcile.setActionCommand("reconcile");
		reconcile.addActionListener(this);

		return reconcile;
	}

	public void actionPerformed(ActionEvent e) {
		if (e.getActionCommand().equals("reconcile")) {
			processReconcileTrades();
		}
	}

	private void processReconcileTrades() {
		Connection conn = DBCreator.getConnection();
		PreparedStatement pstmt = null;
		String sql = "insert into reconciledtrades(sellTradeId, buytradeid, buyQty) values(?,?,?)";
		ArrayList<Integer> reconciledRows = new ArrayList<Integer>();
		int buyQty = 0;
		List<PreparedStatement> pstmtList = new ArrayList<PreparedStatement>();
		for (int i = 0; i < this.buyTradesTable.getRowCount(); i++) {
			if ((Boolean) this.buyTradesTable.getModel().getValueAt(i, 13)) {
				reconciledRows.add(i);
				try {
					pstmt = conn.prepareStatement(sql);
					pstmt.setLong(1, (Long) this.sellTradesTable.getModel()
							.getValueAt(0, 0));
					pstmt.setLong(2, (Long) this.buyTradesTable.getModel()
							.getValueAt(i, 0));
					pstmt.setInt(3, (Integer) this.buyTradesTable.getModel()
							.getValueAt(i, 4));
					pstmtList.add(pstmt);					
				} catch (SQLException e) {
					e.printStackTrace();
				}
				buyQty += (Integer) this.buyTradesTable.getModel().getValueAt(
						i, 4);
				for (int j = 0; j < this.buyTradesTable.getModel()
						.getColumnCount(); j++) {
					System.out.print(this.buyTradesTable.getModel().getValueAt(
							i, j)
							+ ", ");
				}
				System.out.println();
			}
		}
		Collections.sort(reconciledRows);
		Collections.reverse(reconciledRows);

		int sellQty = (Integer) sellTradesTable.getModel().getValueAt(0, 4);
		if (buyQty == sellQty) {
			for (int i = 0; i < reconciledRows.size(); i++) {
				pstmt = pstmtList.get(i);
				try {
					pstmt.execute();
				} catch (SQLException e) {
					e.printStackTrace();
				} finally {
					if (pstmt!=null) {
						pstmt=null;
					}
				}
				((DefaultTableModel) buyTradesTable.getModel()).removeRow(reconciledRows.get(i));
			}
			((DefaultTableModel) baseTable.getModel()).removeRow(baseTable.convertRowIndexToModel(baseTable.getSelectedRow()));
			this.dispose();
		} else {
			JOptionPane.showMessageDialog(this,
					"Buy and Sell Quantities Don't match.", "Error",
					JOptionPane.ERROR_MESSAGE);
		}
	}

	int getBuyCount() {
		return buyTradesTable.getModel().getRowCount();
	}
}
